package com.snowfeel.sfmall.sys.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.snowfeel.sfmall.api.leaf.feign.SegmentFeignClient;
import com.snowfeel.sfmall.core.constants.EntityConstants;
import com.snowfeel.sfmall.core.enums.ResponseCode;
import com.snowfeel.sfmall.core.exception.BizException;
import com.snowfeel.sfmall.core.vo.PageVo;
import com.snowfeel.sfmall.security.util.JwtTokenUtil;
import com.snowfeel.sfmall.security.vo.SecurityUserVo;
import com.snowfeel.sfmall.sys.convert.SysRoleConvert;
import com.snowfeel.sfmall.sys.convert.SysUserConvert;
import com.snowfeel.sfmall.sys.dto.SysUserParam;
import com.snowfeel.sfmall.sys.dto.SysUserRoleParam;
import com.snowfeel.sfmall.sys.mapper.SysMenuRoleMapper;
import com.snowfeel.sfmall.sys.mapper.SysRoleMapper;
import com.snowfeel.sfmall.sys.mapper.SysUserMapper;
import com.snowfeel.sfmall.sys.mapper.SysUserRoleMapper;
import com.snowfeel.sfmall.sys.model.*;
import com.snowfeel.sfmall.sys.query.SysUserQuery;
import com.snowfeel.sfmall.sys.vo.LoginUserVo;
import com.snowfeel.sfmall.sys.vo.SysPermissionVo;
import com.snowfeel.sfmall.sys.vo.SysRoleVo;
import com.snowfeel.sfmall.security.vo.SysUserDetails;
import com.snowfeel.sfmall.sys.vo.SysUserVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * UmsAdminService实现类
 * Created on 2018/4/26.
 */
@Service
public class SysUserService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SysUserService.class);

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysMenuRoleMapper menuRoleMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private SysUserConvert sysUserConvert;

    @Autowired
    private SysRoleConvert sysRoleConvert;

    @Autowired
    private SegmentFeignClient segmentFeignClient;

    //@Autowired
    //private UmsAdminPermissionRelationMapper adminPermissionRelationMapper;
    //
    //@Autowired
    //private UmsAdminPermissionRelationDao adminPermissionRelationDao;

    //@Autowired
    //private UmsAdminLoginLogMapper loginLogMapper;


    public SysUserVo getAdminByUsername(String username) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(SysUser::getUsername, username);
        queryWrapper.last("limit 1");
        SysUser user = userMapper.selectOne(queryWrapper);
        if (Objects.nonNull(user)) {
            return sysUserConvert.convertVo(user);
        }
        return null;
    }

    public SysUserVo register(SysUserParam umsAdminParam) {
        SysUser sysUser = sysUserConvert.convertPo(umsAdminParam);
        sysUser.setStatus(EntityConstants.YES);
        //查询是否有相同用户名的用户
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper();
        wrapper.eq(SysUser::getUsername, sysUser.getUsername());
        List<SysUser> userList = userMapper.selectList(wrapper);
        if (userList.size() > 0) {
            return null;
        }
        //将密码进行加密操作
        String encodePassword = passwordEncoder.encode(sysUser.getPassword());
        sysUser.setPassword(encodePassword);
        userMapper.insert(sysUser);

        SysUserVo userVo = sysUserConvert.convertVo(sysUser);
        userVo.setPassword(null);
        return userVo;
    }

    public String login(String username, String password) {
        String token = null;
        //密码需要客户端加密后传递
        try {
            UserDetails userDetails = loadUserByUsername(username);
            if(!passwordEncoder.matches(password,userDetails.getPassword())){
                throw new BadCredentialsException("密码不正确");
            }
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
//            updateLoginTimeByUsername(username);
//            insertLoginLog(username);
        } catch (AuthenticationException e) {
            LOGGER.warn("登录异常:{}", e.getMessage());
        }
        return token;
    }

    ///**
    // * 添加登录记录
    // * @param username 用户名
    // */
    //private void insertLoginLog(String username) {
    //    UmsAdmin admin = getAdminByUsername(username);
    //    UmsAdminLoginLog loginLog = new UmsAdminLoginLog();
    //    loginLog.setAdminId(admin.getId());
    //    loginLog.setCreateTime(new Date());
    //    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    //    HttpServletRequest request = attributes.getRequest();
    //    loginLog.setIp(request.getRemoteAddr());
    //    loginLogMapper.insert(loginLog);
    //}

    /**
     * 根据用户名修改登录时间
     */
    private void updateLoginTimeByUsername(String username) {
        SysUser record = new SysUser();
        //record.setLoginTime(new Date());

        LambdaUpdateWrapper<SysUser> wrapper = new LambdaUpdateWrapper();
        wrapper.eq(SysUser::getUsername, username);
        userMapper.update(record, wrapper);
    }

    public String refreshToken(String oldToken) {
        return jwtTokenUtil.refreshHeadToken(oldToken);
    }

    public SysUserVo getItem(Long id) {
        SysUser sysUser = userMapper.selectById(id);
        return sysUserConvert.convertVo(sysUser);
    }

    public PageVo<SysUserVo> page(SysUserQuery query) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper();
        if (StringUtils.isNotBlank(query.getName())) {
            wrapper.and(qr ->
                qr.like(SysUser::getUsername, query.getName()).or()
                        .like(SysUser::getRealName, query.getName())
            );
        }
        wrapper.eq(StringUtils.isNotEmpty(query.getPhone()), SysUser::getMobile, query.getPhone());
        wrapper.eq(Objects.nonNull(query.getStatus()), SysUser::getStatus, query.getStatus());
        wrapper.orderByDesc(SysUser::getCreateTime);
        Page<SysUser> page = userMapper.selectPage(new Page<>(query.getPageNo(), query.getPageSize()), wrapper);
        PageVo<SysUserVo> voPage = new PageVo<>();
        List<SysUserVo> sysUserVos = sysUserConvert.convertVoList(page.getRecords());
        voPage.setList(sysUserVos);
        voPage.setPages((int) page.getPages());
        voPage.setTotal(page.getTotal());
        return voPage;
    }

    public int update(Long id, SysUserParam userParam) {
        SysUser entity = userMapper.selectById(id);
        if (Objects.isNull(entity)) {
            throw new BizException(ResponseCode.NOT_FOUND);
        }
        userParam.setId(id);
        //密码已经加密处理，需要单独修改
        userParam.setPassword(null);
        SysUser sysUser = sysUserConvert.convertPo(userParam);
        return userMapper.updateById(sysUser);
    }

    public int delete(Long id) {
        return userMapper.deleteById(id);
    }

    public int updateRole(SysUserRoleParam param) {
        Long userId = param.getUserId();
        List<Long> roleIds = param.getRoleIds();
        int count = roleIds == null ? 0 : roleIds.size();
        //先删除原来的关系
        LambdaUpdateWrapper<SysUserRole> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(SysUserRole::getUserId, userId);
        userRoleMapper.delete(wrapper);

        //建立新关系
        if (!CollectionUtils.isEmpty(roleIds)) {
            for (Long roleId : roleIds) {
                SysUserRole roleRelation = new SysUserRole();
                roleRelation.setUserId(userId);
                roleRelation.setRoleId(roleId);
                userRoleMapper.insert(roleRelation);
            }
        }
        return count;
    }

    public List<SysRoleVo> getRoleList(Long userId) {
        List<SysUserRole> userRoleRelList = getUserRoleRelList(userId);
        Set<Long> roleSet = userRoleRelList.stream().map(SysUserRole::getRoleId).collect(Collectors.toSet());
        LambdaQueryWrapper<SysRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SysRole::getId, Lists.newArrayList(roleSet));
        List<SysRole> sysRoleList = roleMapper.selectList(queryWrapper);
        List<SysRoleVo> sysRoleVos = sysRoleConvert.convertVoList(sysRoleList);
        return sysRoleVos;
    }

    private List<SysUserRole> getUserRoleRelList(Long userId) {
        LambdaQueryWrapper<SysUserRole> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUserRole::getUserId, userId);
        return userRoleMapper.selectList(queryWrapper);
    }

    public List<SysPermissionVo> getPermissionList(Long userId) {
        return menuRoleMapper.getPermissionList(userId);
    }

    public SysUserDetails loadUserByUsername(String username){
        //获取用户信息
        SysUserVo userVo = getAdminByUsername(username);
        if (userVo != null) {
            SecurityUserVo securityUserVo = sysUserConvert.convertSecurityUserVo(userVo);
            List<SysPermissionVo> permissionList = getPermissionList(userVo.getId());
            List<String> list = permissionList.stream().map(SysPermissionVo::getPerms)
                    .collect(Collectors.toList());
            // 查询用户角色列表
            Set<String> roles = roleMapper.rolePermissionByUserId(userVo.getId());
            // 查询用户数据权限
            Integer maximumDataScope = roleMapper.getMaximumDataScope(roles);
            securityUserVo.setRoles(roles);
            securityUserVo.setDataScope(maximumDataScope);
            return new SysUserDetails(securityUserVo, list);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    /**
     * 获取登录用户信息
     * @param username
     * @return
     */
    public LoginUserVo getUserInfo(String username) {
        //获取用户信息
        SysUserVo userVo = getAdminByUsername(username);
        if (userVo != null) {
            SecurityUserVo securityUserVo = sysUserConvert.convertSecurityUserVo(userVo);
            List<SysPermissionVo> permissionList = getPermissionList(userVo.getId());
            List<String> list = permissionList.stream().map(SysPermissionVo::getPerms)
                    .collect(Collectors.toList());
            // 查询用户角色列表
            Set<String> roles = roleMapper.rolePermissionByUserId(userVo.getId());
            // 查询用户数据权限
            Integer maximumDataScope = roleMapper.getMaximumDataScope(roles);
            securityUserVo.setRoles(roles);
            securityUserVo.setDataScope(maximumDataScope);

            return new LoginUserVo(securityUserVo, list);
        }
        return null;
    }
}
